--request.lua
-- 处理传过来的协议的调用
local filename = "talkrequest.lua"

require "skynet.manager"
require "imenum"

local skynet = require "skynet"
local filelog = require "filelog"
local tabletool = require "tabletool"
local timetool = require "timetool"
local configdao = require "configdao"
local timer = require "timer"
local cluster = require "skynet.cluster"
local md5 = require "md5"

local json = require "cjson"
json.encode_sparse_array(true, 1, 1)

local CMD = {}
local service = nil
local talklogic = nil

function CMD.init(caller)
	service = caller
	talklogic = service:get_logicbyname("talklogic")
end

--[Comment]
-- 处理发来的request类消息
--
function CMD.request( msgname, rid, roledata, request, ...)
    --转化request协议
    local is_request = false
    if msgname == "request" then
        msgname = request.msgname or ""
        request = json.decode(request.msgbody) or { }
        is_request = true
    end

    local f = CMD[msgname]
    if f == nil then
        return {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "消息不存在！"}
    end

    local talkobj = service.talker_data
    local responsemsg = {}
    --删除桌子中，返回错误
    if talkobj.isdeleting then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
		responsemsg.retstr = "桌子不存在！"
    else
        responsemsg = f(rid, roledata, request, ...)
    end

    --request消息转化消息格式
    if is_request then
        return { msgname = msgname .. "R", msgbody = responsemsg}
    end
    
    return responsemsg
end

-------------------------

--[Comment]
-- 进桌
-- 正常由router调起,request为空
-- rid  玩家id
-- roledata 玩家信息 {info,money}
-- ret 返回table_gameinfo（牌局信息）
--
function CMD.entertalk( rid, roledata,request)
	local response = {}
    local playerinfo = roledata.info or { }
    local playermoney = roledata.money or { }
	local talker_data = service.talker_data

    --删除桌子中，返回错误
    if talker_data.isdeleting then
        response.retcode = EErrCode.ERR_INVALID_REQUEST
		response.retstr = "桌子不存在！"
		return	response
    end

    --检测是否已在其他桌子内
    -- if cluster.call("gatenode", ".router", "check_role_state", rid, 0) then
    --     local status, send_map = skynet.pcall(skynet.call, ".router", "lua", "get_role_data", rid)
    --     if not status or not send_map then
    --         response.retcode = EErrCode.ERR_HAD_IN_TABLE
		  --   response.retstr = "已经在其他桌子内"
		  --   return	response
    --     end
    -- end

	if talker_data.sitdown_player_num >= talker_data.conf.max_player_num then
        if talker_data.rid ~= 0 and talker_data.rid ~= rid then
		  response.retcode = EErrCode.ERR_TABLE_FULL
		  response.retstr = "房间已满！"
		  return response
        end
	end
    --执行进桌逻辑
    talklogic.entertalk(talker_data, rid, roledata, request)
    response.rid = rid
    response.talk_index = talker_data.index
	return response
end

function CMD.opensession(rid, roledata, request)
    local responsemsg = {}
    local playerinfo = roledata.info or {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.send_to_rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不能为空"
        return responsemsg
    end
    if request.send_to_rid == rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不能给自己发消息"
        return responsemsg
    end
    local send_to_rid = tonumber(request.send_to_rid)
    ----检测是否有这个玩家
    local status, is_exist, info = skynet.pcall(skynet.call, ".talkcache", "lua", "checkrid", send_to_rid)
    if not status or not is_exist then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不存在"
        return responsemsg
    end
    local from_rid = send_to_rid
    local to_rid = rid
    local status, result = skynet.pcall(skynet.call, ".autoreplay", "lua", "sendautoreplay", "welcome", from_rid, to_rid)
    talklogic.update_talk_heart_time(talker_data)
    return responsemsg
end

function CMD.sendmessage(rid, roledata, request)
    --filelog.sys_error("----------CMD.sendmessage------", rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.message then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "消息不能为空"
        return responsemsg
    end

    if not request.send_to_rid or tonumber(request.send_to_rid) < 10000 
        or talker_data.rid == tonumber(request.send_to_rid) then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不合法"
        return responsemsg
    end

    if not request.message or type(request.message) ~= "string" 
        or string.len(request.message) == 0 then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "消息内容不能为空"
        return responsemsg
    end

    local send_to_rid = tonumber(request.send_to_rid)
    ----检测是否有这个玩家
    local status, is_exist, info = skynet.pcall(skynet.call, ".talkcache", "lua", "checkrid", send_to_rid)
    if not status or not is_exist then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不存在"
        return responsemsg
    end

    if info.level == 99 then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不合法"
        return responsemsg
    end
    talklogic.update_talk_heart_time(talker_data)
    local send_to_name = info.rolename
    talker_data.last_send_time = timetool.get_time()
    local is_replay = talklogic.check_is_willautoreplay(rid, request)
    filelog.sys_error("-----is_replay-----", is_replay, request)
    if is_replay == true then
        local uuid = skynet.call(".nodeuuid", "lua", "getuuid")
        local newmessage = {
            keyid               = uuid,
            since_rid           = talker_data.rid,
            send_to_rid         = send_to_rid,
            send_to_name        = send_to_name,
            msg                 = request.message,
            sendtime            = timetool.get_time(),
        }
        responsemsg.message = json.encode(newmessage)
        return responsemsg
    end
    ----检查是否在imnode上
    local status, send_map = skynet.pcall(skynet.call, ".router", "lua", "get_role_data", send_to_rid)

    if not status or not send_map then
        --[[
        // 通知大厅有新消息
        message messagegateN{
            optional int32 newmessage_num = 1;
        }
        --]]
        skynet.send(".noticemgr", "lua", "push_notice", send_to_rid, 1)
        local uuid = skynet.call(".nodeuuid", "lua", "getuuid")
        local newmessage = {
            keyid               = uuid,
            since_rid           = talker_data.rid,
            send_to_rid         = send_to_rid,
            send_to_name        = send_to_name,
            msg                 = request.message,
            sendtime            = timetool.get_time(),
        }
        local status, success = skynet.pcall(skynet.call, ".talkcache", "lua", "pushmessageincache", talker_data.rid, send_to_rid, newmessage, true)
        ---filelog.sys_error("-------not on imnuode------", status, success)
        status, success = skynet.pcall(skynet.call, ".talkcache", "lua", "pushmessageincache", send_to_rid, talker_data.rid, newmessage, false)
        responsemsg.message = json.encode(newmessage)
        return responsemsg
    else
        local send_to_talk_service = send_map.talk_service
        local uuid = skynet.call(".nodeuuid", "lua", "getuuid")
        local newmessage = {
            keyid               = uuid,
            since_rid           = talker_data.rid,
            send_to_rid         = send_to_rid,
            send_to_name        = send_to_name,
            msg                 = request.message,
            sendtime            = timetool.get_time(),
        }
        local status, success = skynet.pcall(skynet.call, send_to_talk_service, "lua", "cmd", "push_message", send_to_rid, newmessage, talker_data.rid)
        ---放入缓存
        status, success = skynet.pcall(skynet.call, ".talkcache", "lua", "pushmessageincache", talker_data.rid, send_to_rid, newmessage, true)
        status, success = skynet.pcall(skynet.call, ".talkcache", "lua", "pushmessageincache", send_to_rid, talker_data.rid, newmessage, true)
        responsemsg.message = json.encode(newmessage)
        return responsemsg
    end
end

function CMD.leavetalk(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "rid 错误"
        return responsemsg
    end
    talklogic.leavetalk(talker_data, request)
    talklogic.update_talk_heart_time(talker_data)
    return responsemsg
end


function CMD.reentertalk(rid, roledata, request)
    local responsemsg = {}

    local talker_data = service.talker_data

     --桌子索引错误
    if request and request.talk_index and request.talk_index ~= talker_data.index then
        --从当前桌子离开
        skynet.send(".router","lua","leave_talk", nil, rid, talker_data.index)
        return {retcode = EErrCode.ERR_INVALID_REQUEST,retstr = "错误的桌子索引号！"}
    end

    if talker_data.rid ~= rid then
        skynet.send(".router","lua","leave_talk", nil, rid, talker_data.index)
        return {retcode = EErrCode.ERR_INVALID_REQUEST,retstr = "错误的桌子索引号！"}
    end

    talklogic.reentertalk(talker_data, request)
    talklogic.update_talk_heart_time(talker_data)
    responsemsg.rid = rid
    responsemsg.talk_index = talker_data.index
    return responsemsg
end
--[[
// 发送充值信息(玩家端操作)
message sendvipcharge{
    required int32 send_to_rid = 1;
    required int32 charge_type = 2;
    required int32 charge_num  = 3; // 分
}
--]]

function CMD.sendvipcharge(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data

    if talker_data.talk_type ~= IMCLIENTTYPE.CLIENT_TYPE_PLAYER then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "只能玩家端操作!"
        return responsemsg
    end

    if not request.send_to_rid or request.send_to_rid < 10000 or talker_data.rid == request.send_to_rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不合法"
        return responsemsg
    end

    if not request.charge_type or request.charge_type < IMCHARGETYPE.TYPE_ALIPAY 
        or request.charge_type > IMCHARGETYPE.EWITHDRAW_TYPE_BANKCARD then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "充值类型不正确"
        return responsemsg
    end

    if not request.charge_num or request.charge_num < 0 then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST


    end

    local send_to_rid = request.send_to_rid
    ----检测是否有这个玩家
    local status, is_exist = skynet.pcall(skynet.call, ".talkcache", "lua", "checkrid", send_to_rid)
    if not status or not is_exist then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不存在"
        return responsemsg
    end

    local send_to_rid = request.send_to_rid
    ----检查是否在imnode上
    local status, send_map = skynet.pcall(skynet.call, ".router", "lua", "get_role_data", send_to_rid)

    return responsemsg
end


function CMD.deletemessage(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.keyid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "消息id不能为空"
        return responsemsg
    end
    talklogic.update_talk_heart_time(talker_data)
    local status, result = skynet.pcall(skynet.call, ".talkcache", "lua", "deletemessage", rid, request.keyid)
    return responsemsg
end

function CMD.cleanmessages(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.send_to_rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "发送玩家rid不能为空"
        return responsemsg
    end

    local send_to_rid = request.send_to_rid
    ----检测是否有这个玩家
    local status, is_exist = skynet.pcall(skynet.call, ".talkcache", "lua", "checkrid", send_to_rid)
    if not status or not is_exist then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不存在"
        return responsemsg
    end
    talklogic.update_talk_heart_time(talker_data)
    local status, result = skynet.pcall(skynet.call, ".talkcache", "lua", "cleanmessages", rid, send_to_rid)
    return responsemsg
end

function CMD.getmessage(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.send_to_rid or not request.last_keyid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "参数不正确"
        return responsemsg
    end
    local status, result, getmessages = skynet.pcall(skynet.call, ".talkcache", "lua", "getmessagecache", rid, request.send_to_rid)
    ---filelog.sys_error("------status, result--------", status, result, getmessages)
    if status and result then
        responsemsg.messages = {}
        local allmessages = {}
        for index, getmessage in ipairs(getmessages) do
            --[[
                message messageitem{
                    optional int64      keyid               = 1;
                    optional int32      since_rid           = 2;
                    optional int32      send_to_rid         = 3;
                    optional int32      message_type        = 4;
                    optional int32      message_state       = 5;
                    optional string     message_content     = 6;
                    optional int32      message_sendtime    = 7; //发送时间
                }
            --]]
            if request.last_keyid < getmessage.keyid then
                local messageitem = {
                    keyid                   = getmessage.keyid,
                    since_rid               = getmessage.sendrid,
                    send_to_rid             = getmessage.destorid,
                    send_to_name            = getmessage.send_to_name,
                    msg                     = getmessage.msg,
                    sendtime                = getmessage.message_sendtime,
                }
                table.insert(allmessages, messageitem)
            end
        end
        table.sort(allmessages, function(first, second)
                if first.keyid < second.keyid then
                    return true
                else
                    return false
                end
            end)
        for index, allmessage in ipairs(allmessages) do
            table.insert(responsemsg.messages, json.encode(allmessage))
            if #responsemsg.messages >= 30 then break end
        end
    end
    talklogic.update_talk_heart_time(talker_data)
    ---filelog.sys_error("-------getmessage-----responsemsg------------", responsemsg)
    return responsemsg
end

---获取所有聊天玩家的rid
function CMD.getalltalkrids(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    ---获取所有和玩家rid聊天的rid
    local alltalkrids = {}
    local status, result = skynet.pcall(skynet.call, ".talkcache", "lua", "get_alltalkrids", rid)
    ---filelog.sys_error("------get_alltalkrids-----status, result-------", rid, status, result)
    if not status or not result or next(result) == nil then
    else
        for index, talkrid in pairs(result) do
            table.insert(alltalkrids, talkrid)
        end
    end
    talklogic.update_talk_heart_time(talker_data)
    responsemsg.alltalkrids = alltalkrids
    return responsemsg
end

--
--玩家断开连接
--
function CMD.disconnect(rid, roledata,request)
	---filelog.print("----tablerequest.disconnect----", rid)
	local talkobj = service.talker_data
    talklogic.disconnect(talkobj,request)
    return true
end
--
--清除玩家状态
--
function CMD.clear_player_state(rid, roledata, request)
    if not rid or rid <= 0 then
        return
    end
end

--请求次数
local request_cnt = 0
--请求失败次数
local requesterr_cnt = 0
--上次请求时间
local last_reqtime = 0
 --请求超时时间，5s
local request_outtime = 5
--最大同时请求次数
local max_syncreq_cnt = 2

function CMD.gmhttprequest(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        return { retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "玩家rid不正确"}
    end

    local talker_rid = tonumber(talker_data.rid)
    ----检测是否有这个玩家
    local status, is_exist, info = skynet.pcall(skynet.call, ".talkcache", "lua", "checkrid", talker_rid)
    if not status or not is_exist then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家不存在"
        return responsemsg
    end

    --请求中，直接返回
    local curtime = timetool.get_time()
    if requesterr_cnt > 0 then
        if (curtime - last_reqtime) < requesterr_cnt then
            return { retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "系统繁忙，请稍后重试"}
        end
    end
    if request_cnt >= max_syncreq_cnt then
        if (curtime - last_reqtime) < request_outtime then
            return { retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "网络繁忙，请稍后重试"}
        end
        request_cnt = 1
    else
        request_cnt = request_cnt + 1
    end
    --验证参数合法性
    local request_url = tostring(request.request_url) or ""
    if request_url == "" then
        request_cnt = request_cnt - 1
        return {retcode = EErrCode.ERR_INVALID_REQUEST,retstr = "无效的请求"}
    end
    talklogic.update_talk_heart_time(talker_data)
    local sm_key = configdao.get_common_conf("sm_key") or ""
    --设置签名
    local sign = md5.sumhexa(curtime .. sm_key) .. curtime
    --发送http请求
    last_reqtime = curtime
    local result = skynet.call(".httpservice", "lua", "send_http_request", rid, request_url)
    request_cnt = request_cnt - 1
    if result then
        requesterr_cnt = 0
        return {response_url = result, callback_addr = request.callback_addr}
    elseif result == false then
        if requesterr_cnt == 0 then
            requesterr_cnt = 1
        else
            requesterr_cnt = requesterr_cnt * 2
        end
    end
    return { retcode = EErrCode.ERR_NET_EXCEPTION, retstr = "请求失败" }
end

function CMD.setwelcomewords(rid, roledata, request)
    local responsemsg = {}
    local playerinfo = roledata.info or {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end
    if not request.setwords or request.setwords == "" then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = ""
    end

    -- local check_vip = talklogic.check_player_is_vip(rid)
    -- ----filelog.sys_error("--------------check_vip--------", check_vip)
    -- if not check_vip then
    --     responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
    --     responsemsg.retstr = "你不是vip权限不足"
    --     return responsemsg
    -- end

    local status, set_contents = skynet.pcall(json.decode, request.setwords)
    filelog.sys_error("-------status, set_contents------", status, set_contents)

    local set_status, set_result = skynet.pcall(skynet.call, ".autoreplay", "lua", "setwords", rid, set_contents)
    filelog.sys_error("-----set_status, set_result------", set_status, set_result)
    return responsemsg
end

function CMD.getallsetwords(rid, roledata, request)
    local responsemsg = {}
    local talker_data = service.talker_data
    if talker_data.rid ~= rid then
        responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
        responsemsg.retstr = "玩家rid不正确"
        return responsemsg
    end

    -- local check_vip = talklogic.check_player_is_vip(rid)
    -- if not check_vip then
    --     responsemsg.retcode = EErrCode.ERR_INVALID_REQUEST
    --     responsemsg.retstr = "你不是vip权限不足"
    --     return responsemsg
    -- end
    local get_status, get_result = skynet.pcall(skynet.call, ".autoreplay", "lua", "getallsetwords", rid)
    filelog.sys_error("-----get_status, get_result-----", get_status, get_result)
    if not get_status then
        return responsemsg
    else
        if get_result ~= nil then
            responsemsg.setwords = {}
            table.insert(responsemsg.setwords, get_result)
            return responsemsg
        else
            return responsemsg
        end
    end
end

return CMD